package com.cskaoyan.market.admin.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import com.cskaoyan.market.db.mapper.MarketCommentMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;

import com.cskaoyan.market.admin.bo.ChannelBO;
import com.cskaoyan.market.admin.service.AdminOrderService;
import com.cskaoyan.market.db.domain.*;
import com.cskaoyan.market.db.mapper.MarketOrderGoodsMapper;
import com.cskaoyan.market.db.mapper.MarketOrderMapper;
import com.cskaoyan.market.db.mapper.MarketUserMapper;
import com.cskaoyan.market.util.AdminResponseCode;
import com.cskaoyan.market.util.MarketConstant;
import com.cskaoyan.market.util.MyBatisUtil;
import com.cskaoyan.market.util.OrderStatus;
import com.github.pagehelper.PageHelper;

/**
 * @author BlackFlame33
 * @date 2023/03/20
 **/
public class AdminOrderServiceImpl implements AdminOrderService {
    @Override
    public List<MarketOrder> getOrderList(Integer page, Integer limit, Short[] orderStatusArray, String sort,
        String order, String start, String end, Integer userId, String orderSn) {
        SqlSession session = MyBatisUtil.getSession();
        MarketOrderMapper mapper = session.getMapper(MarketOrderMapper.class);
        MarketOrderExample marketOrderExample = new MarketOrderExample();
        MarketOrderExample.Criteria criteria = marketOrderExample.createCriteria();
        if (orderStatusArray != null) {
            for (Short orderStatus : orderStatusArray) {
                if (orderStatus != null) {
                    criteria.andOrderStatusEqualTo(orderStatus);
                }
            }
        }
        if (StringUtils.isNotEmpty(start) && StringUtils.isNotEmpty(end)) {
            criteria.andAddTimeBetween(LocalDateTime.parse(start, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
                LocalDateTime.parse(end, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }
        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        if (StringUtils.isNotEmpty(orderSn)) {
            criteria.andOrderSnEqualTo(orderSn);
        }
        criteria.andDeletedEqualTo(MarketOrder.Deleted.NOT_DELETED.getValue());
        marketOrderExample.setOrderByClause(sort + " " + order);
        PageHelper.startPage(page, limit);
        List<MarketOrder> marketOrders = mapper.selectByExample(marketOrderExample);
        session.commit();
        session.close();
        return marketOrders;
    }

    @Override
    public Map<String, Object> getOrderDetail(Integer id) {
        Map<String, Object> data = new HashMap<>();
        SqlSession session = MyBatisUtil.getSession();
        MarketOrderMapper marketOrderMapper = session.getMapper(MarketOrderMapper.class);
        MarketOrder order = marketOrderMapper.selectByPrimaryKey(id);
        data.put("order", order);
        MarketUserMapper marketUserMapper = session.getMapper(MarketUserMapper.class);
        MarketUser marketUser = marketUserMapper.selectByPrimaryKey(order.getUserId());
        Map<String, String> user = new HashMap<>();
        user.put("nickname", marketUser.getNickname());
        user.put("avatar", marketUser.getAvatar());
        data.put("user", user);
        MarketOrderGoodsMapper marketOrderGoodsMapper = session.getMapper(MarketOrderGoodsMapper.class);
        MarketOrderGoodsExample marketOrderGoodsExample = new MarketOrderGoodsExample();
        marketOrderGoodsExample.or().andOrderIdEqualTo(order.getId());
        List<MarketOrderGoods> orderGoods = marketOrderGoodsMapper.selectByExample(marketOrderGoodsExample);
        data.put("orderGoods", orderGoods);
        return data;
    }

    @Override
    public Integer refundOrder(Integer orderId, BigDecimal refundMoney) {
        SqlSession session = MyBatisUtil.getSession();
        MarketOrderMapper mapper = session.getMapper(MarketOrderMapper.class);
        int code;
        try {
            MarketOrder order = mapper.selectByPrimaryKey(orderId);
            order.setRefundAmount(refundMoney);
            order.setRefundType(MarketConstant.MARKET_REFUND_TYPE);
            order.setRefundTime(LocalDateTime.now());
            order.setOrderStatus(OrderStatus.REFUNDED);
            code = mapper.updateByPrimaryKey(order);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return -1;
        } finally {
            session.close();
        }
        return 0;
    }

    @Override
    public List<ChannelBO> getChannelList() throws IOException {
        List<ChannelBO> data = new LinkedList<>();
        try (BufferedReader bufIn = new BufferedReader(new InputStreamReader(
            Objects.requireNonNull(AdminOrderServiceImpl.class.getClassLoader().getResourceAsStream("channel.txt"))))) {
            String line;
            String[] split;
            while ((line = bufIn.readLine()) != null) {
                split = line.split("=");
                ChannelBO channelBO = new ChannelBO();
                channelBO.setCode(split[0]);
                channelBO.setName(split[1]);
                data.add(channelBO);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

    @Override
    public int shipOrder(Integer orderId, String shipChannel, String shipSn) {
        SqlSession session = MyBatisUtil.getSession();
        MarketOrderMapper mapper = session.getMapper(MarketOrderMapper.class);
        MarketOrder order = mapper.selectByPrimaryKey(orderId);
        order.setShipChannel(shipChannel);
        order.setShipSn(shipSn);
        order.setShipTime(LocalDateTime.now());
        order.setOrderStatus(OrderStatus.SHIPPED);
        int code = mapper.updateByPrimaryKey(order);
        session.commit();
        session.close();
        return code;
    }

    @Override
    public int deleteOrder(Integer orderId) {
        SqlSession session = MyBatisUtil.getSession();
        MarketOrderMapper mapper = session.getMapper(MarketOrderMapper.class);
        MarketOrder order = mapper.selectByPrimaryKey(orderId);
        if (!(Objects.equals(order.getOrderStatus(), OrderStatus.USER_RECEIPT)
            || Objects.equals(order.getOrderStatus(), OrderStatus.SYSTEM_RECEIPT))) {
            return AdminResponseCode.ORDER_DELETE_FAILED;
        }
        order.setUpdateTime(LocalDateTime.now());
        order.setDeleted(true);
        int code;
        try {
            code = mapper.updateByPrimaryKey(order);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return AdminResponseCode.ORDER_DELETE_FAILED;
        }
        return code;
    }

    @Override
    public void reply(String commentId, String content) {
        SqlSession session = MyBatisUtil.getSession();
        MarketCommentMapper mapper = session.getMapper(MarketCommentMapper.class);
        MarketComment marketComment = mapper.selectByPrimaryKey(Integer.valueOf(commentId));
        marketComment.setUpdateTime(LocalDateTime.now());
        marketComment.setAdminContent(content);
        mapper.updateByPrimaryKey(marketComment);
        session.commit();
        session.close();
    }
}